package main

import (
	"fmt"
	cache "gitee.com/hyc343592318/go-multi-lev-cache"
	"log"
	"math"
	"math/rand"
	"net/http"
	_ "net/http/pprof"
	"sync"
	"time"
)

var (
	testTotal = math.MaxInt16
)

var appName = "测试样例-"

func main() {
	cache.CacheDebug = true
	cache.CacheMonitor = true
	cache.CacheMonitorSecond = 10
	cache.OutCachePubSub = true
	cache.EntryLazyFactor = 18
	cache.DefaultGPoolWorkerNum = 20
	cache.DefaultGPoolJobQueueChanLen = 300
	cache.DefaultFreeCacheSize = 100 * 1024 * 1024 // 100MB
	cache.DefaultPubSubRedisChannel = "cache-pubsub-channel"
	cache.DefaultRedisConf.DSN = "127.0.0.1:6379"
	cache.DefaultRedisConf.DB = 1
	cache.DefaultRedisConf.Pwd = ""
	cache.DefaultRedisConf.MaxConn = 30
	cache.DefaultPubSubRedisConf = cache.DefaultRedisConf
	c, err := cache.New(nil, nil)
	if err != nil {
		log.Println("缓存Start ----------> ", err)
		return
	}
	go func() {
		http.HandleFunc("/statics", func(writer http.ResponseWriter, request *http.Request) {
			m := cache.HitStatisticsOut.String()
			_, _ = writer.Write([]byte(m))
		})
		port := 6089
		addr := fmt.Sprintf("localhost:%d", port)
		log.Printf("缓存统计数据记录地址: %s\n", addr)
		err := http.ListenAndServe(addr, nil)
		if err != nil {
			log.Printf("server listen err = [%v]", err)
		}
	}()

	wg := &sync.WaitGroup{}
	wg.Add(20)
	for i := 0; i < 10; i++ {
		go getKey(c, wg)
	}
	for i := 0; i < 5; i++ {
		go setKey(c, wg)
	}
	for i := 0; i < 5; i++ {
		go delKey(c, wg)
	}
	wg.Wait()
	c.Close()
}

func delKey(c *cache.MultiCache, wg *sync.WaitGroup) {
	defer wg.Done()
	for i := 0; i < testTotal; i++ {
		key := cache.GenKey(appName, rand.Intn(math.MaxInt8))
		err := c.Del(key, false)
		if err != nil {
			log.Fatalln(err)
		}
		time.Sleep(1 * time.Second)
	}
}

func setKey(c *cache.MultiCache, wg *sync.WaitGroup) {
	defer wg.Done()
	for i := 0; i < testTotal; i++ {
		key := cache.GenKey(appName, rand.Intn(math.MaxInt8))
		obj := &Object{
			ID:      i,
			Value:   key,
			Address: []string{"缓存数据1", appName},
			Car: &Car{
				Name:  "缓存数据2",
				Price: float64(i) / 100,
			},
		}
		err := c.Set(key, obj, 30, true) // ttl is second
		if err != nil {
			log.Fatalln(err)
		}
		time.Sleep(2 * time.Second)
	}
}

func getKey(c *cache.MultiCache, wg *sync.WaitGroup) {
	defer wg.Done()
	for i := 0; i < testTotal; i++ {
		key := cache.GenKey(appName, rand.Intn(math.MaxInt8))
		var o Object
		// ttl is second
		err := c.Get(key, 30, &o, func() (interface{}, error) {
			time.Sleep(50 * time.Millisecond)
			return &Object{
				ID:      i,
				Value:   key,
				Address: []string{"缓存数据1", appName},
				Car: &Car{
					Name:  "缓存数据2",
					Price: float64(i) / 100,
				},
			}, nil
		})
		if err != nil {
			log.Fatalln(err)
		}
		//out,err := jsoniter.MarshalToString(o)
		//if err != nil {
		//	log.Println(err)
		//	return
		//}
		//fmt.Printf("%s\n",out)
		time.Sleep(2 * time.Second)
	}
}

type Object struct {
	ID      int      `json:"id"`
	Value   string   `json:"value"`
	Address []string `json:"address"`
	Car     *Car     `json:"car"`
}

type Car struct {
	Name  string  `json:"name"`
	Price float64 `json:"price"`
}

//func (o *Object) DeepCopy() interface{} {
//	return &(*o)
//}

func init() {
	rand.Seed(time.Now().UnixNano())
	appName += fmt.Sprintf("%d", rand.Intn(100))
}
